#!/usr/bin/python
####################################################################################
####################################################################################
##      Author: Ahmed Adel Mohamed
##      Date: 27/04/2011
##      Version: 1.0.3
##      Puropse:
##              Script to arrange Cisco Access list by 
##              Number of hits, it has one argument 
##              which is the access-list file name
##          
##   Copyright (C) 2011  Ahmed Adel
##
##   This program is free software: you can redistribute it and/or modify
##   it under the terms of the GNU General Public License as published by
##   the Free Software Foundation, either version 3 of the License, or
##      (at your option) any later version.
##
##   This program is distributed in the hope that it will be useful,
##   but WITHOUT ANY WARRANTY; without even the implied warranty of
##   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##   GNU General Public License for more details.
##
##   You should have received a copy of the GNU General Public License
##   along with this program.  If not, see <http://www.gnu.org/licenses/>.
####################################################################################
####################################################################################
# Import Modules
import string
import re
import sys
import getopt
#Functions
# Function to perform and operation between IP address and subnet mask
def and_list(list_IP, list_Mask):
    and_output = []
    counter = ""
#    print(list_IP)
#    print(list_Mask)
    for counter in range(len(list_IP)):
        and_output.append(int(list_IP[counter]) & int(list_Mask[counter]))
    return and_output;
# Function to compare the IP as a Source IP
def comp_source(access_list, array_IP):
	#print(access_list)
	if access_list[7] == "any":
		print(' '.join(access_list))
        
	elif access_list[7] == "host":
		IP = "".join(array_IP)
		array_Source = access_list[8].split(".")
		Source = "".join(array_Source)
		if IP == Source:
		    print(' '.join(access_list))
	elif access_list[4] == "standard":
		array_Mask = access_list[7].split(".")
		array_Source = access_list[6].split(".")
		IP_Mask = and_list(array_IP, array_Mask)
		IP_Mask = map(str, IP_Mask)
		IP = "".join(IP_Mask)
		Source = "".join(array_Source)
		if IP == Source:
		    print(' '.join(access_list))
	elif access_list[4] == "webtype":
		return;
	else:
		array_Mask = access_list[8].split(".")
		array_Source = access_list[7].split(".")
		IP_Mask = and_list(array_IP, array_Mask)
		IP_Mask = map(str, IP_Mask)
		IP = "".join(IP_Mask)
		Source = "".join(array_Source)
		if IP == Source:
		    print(' '.join(access_list))
	return;
# Function to compare the IP as a Destination IP
def comp_dest(access_list, array_IP):
   # print(access_list)
    if access_list[7] == "any":
        if access_list[8] == "any":
            print(' '.join(access_list))
        elif access_list[8] == "host":
            IP = "".join(array_IP)
            array_Dest = access_list[9].split(".")
            Dest = "".join(array_Dest)
            if IP == Dest:
                print(' '.join(access_list))
        else:
            array_Mask = access_list[9].split(".")
            array_Dest = access_list[8].split(".")
            IP_Mask = and_list(array_IP, array_Mask)
            IP_Mask = map(str, IP_Mask)
            IP = "".join(IP_Mask)
            Dest = "".join(array_Dest)
            if IP == Dest:
                print(' '.join(access_list))
    elif access_list[9] == "host":
            IP = "".join(array_IP)
            array_Dest = access_list[10].split(".")
            Dest = "".join(array_Dest)
            if IP == Dest:
                print(' '.join(access_list))
    elif access_list[9] == "range":
	    if access_list[12] == "any":
            	print(' '.join(access_list))
            elif access_list[12] == "host":
            	IP = "".join(array_IP)
            	array_Dest = access_list[13].split(".")
            	Dest = "".join(array_Dest)
            	if IP == Dest:
                	print(' '.join(access_list))
            else:
            	array_Mask = access_list[13].split(".")
            	array_Dest = access_list[12].split(".")
            	IP_Mask = and_list(array_IP, array_Mask)
            	IP_Mask = map(str, IP_Mask)
            	IP = "".join(IP_Mask)
            	Dest = "".join(array_Dest)
            	if IP == Dest:
                	print(' '.join(access_list))
    elif access_list[9] == "eq":
	     if access_list[11] == "any":
            	print(' '.join(access_list))
             elif access_list[11] == "host":
            	IP = "".join(array_IP)
            	array_Dest = access_list[12].split(".")
            	Dest = "".join(array_Dest)
            	if IP == Dest:
                	print(' '.join(access_list))
             else:
            	array_Mask = access_list[12].split(".")
            	array_Dest = access_list[11].split(".")
            	IP_Mask = and_list(array_IP, array_Mask)
            	IP_Mask = map(str, IP_Mask)
            	IP = "".join(IP_Mask)
            	Dest = "".join(array_Dest)
            	if IP == Dest:
                	print(' '.join(access_list))
    elif access_list[4] == "standard":
	    return;
    elif access_list[4] == "webtype":
		return;
    else:
        if access_list[9] == "any":
            print(' '.join(access_list))
	elif access_list[11] == "any":
		print(' '.join(access_list))
        else:
            array_Mask = access_list[10].split(".")
            array_Dest = access_list[9].split(".")
            IP_Mask = and_list(array_IP, array_Mask)
            IP_Mask = map(str, IP_Mask)
            IP = "".join(IP_Mask)
            Dest = "".join(array_Dest)
            if IP == Dest:
                print(' '.join(access_list))
            
    return;
# Define Variables
access_line = []
IP = ""
IP_type = "s"
# Get script arguments
if len(sys.argv) < 2:
        print("!!!!!! please enter the access-list file name !!!!!!")
        sys.exit()
else:
    optlist, args = getopt.getopt(sys.argv[1:], 's:d:')
    for o, a in optlist:
        if o == '-s':
            IP = a
            IP_type = "s"
        elif o == '-d':
            IP = a
            IP_type = "d"
        else:
            print("!!!!!! Please enter source or destination IP address !!!!!!")
            sys.exit()
    access_file = args[0]
    
# Open access list file to read access list lines
Input = open(access_file, "r")
# Read access lists from access list file
Lines = Input.readlines()
# Prepare IP address for testing
array_IP = IP.split(".")
# define Regular expressoin variables used in access list comparisons
reg1 = re.compile("line")
reg2 = re.compile("inactive")
reg3 = re.compile("nat0", re.IGNORECASE)
reg4 = re.compile("object-group", re.IGNORECASE)
reg5 = re.compile("remark", re.IGNORECASE)
regnum = re.compile('\d+')
# Loop on access lists
for line in Lines:
# Ignore access list lines which are inactive, used for nat, contains the object-group keyword or a remark
        if reg2.search(line) or reg3.search(line) or reg4.search(line) or reg5.search(line):
            continue
        # skip empty lines if found
        if not line.strip():
            continue
        if reg1.search(line):
            access_line = line.split()
            if IP_type == "s":
                comp_source(access_line, array_IP)
            elif IP_type == "d":
		#print(access_line)
                comp_dest(access_line, array_IP)
